package component;

import annotation.Autowired;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Ioc {
    private static volatile Ioc ioc;
    /**
     * 三个对象池用于解决循环依赖
     */
    private static Map<String,Object> factoryBean;//对象初始化所在位置
    private static Map<String,Object> beanPool;//对象正在注入属性时所在位置
    private static Map<String,Object> bean;//最终对象所在位置
    private Ioc(){}

    /**
     * 单例获取Ioc容器
     * @return ioc
     */
    public static Ioc getIoc(){
        if(ioc == null){
            synchronized (Ioc.class){
                ioc = new Ioc();
                factoryBean = new ConcurrentHashMap<>();
                bean = new ConcurrentHashMap<>();
                beanPool = new ConcurrentHashMap<>();
            }
        }
        return ioc;
    }

    /**
     * 启动时将对象全部加入factoryBean池
     * @param str
     * @param obj
     */
    public static void insertFactoryBean(String str, Object obj){
        factoryBean.put(str,obj);
    }

    /**
     * 获取一个Bean
     * @param str
     * @return
     */
    public static synchronized Object getBean(String str) {
        if(bean.get(str) != null){//首先检查是否已存在对象
            return bean.get(str);
        }
        else if(factoryBean.get(str) != null){ //判断其是否还未创建
            if(factoryBean.get(str) instanceof String) {    //检查是否为多例对象
                try {
                    return Class.forName(str).getDeclaredConstructor().newInstance();
                } catch (ReflectiveOperationException e) {
                    e.printStackTrace();
                }
            }
            else {//否则就是一个未初始化的单例对象
                Class<?> klass = factoryBean.get(str).getClass();
                Object objectBean = factoryBean.get(str); //在未初始化对象池删除对象，并在正在初始化池加入
                beanPool.put(str,factoryBean.get(str));
                factoryBean.remove(str);
                Field[] fields = klass.getDeclaredFields();
                Autowired autowired;
                for(Field field : fields){
                    if( (autowired = field.getDeclaredAnnotation(Autowired.class)) != null){
                        String[] names = field.getType().toString().split("\\.");
                        Object object = getBean(names[names.length-1]);
                        try {
                            field.set(objectBean,object);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
                bean.put(str,objectBean);
                beanPool.remove(str);//正在初始化对象池删除该对象，并在初始化完成的对象池中加入该对象
                return bean.get(str);
            }
        }else if(beanPool.get(str) != null){ //如果在正在初始化池beanPool中，将其加入bean池并初始化。
            bean.put(str,beanPool.get(str));
            beanPool.remove(str);
            return bean.get(str);
        }else{
            try {
                throw new ClassNotFoundException("请检查是否依赖循环有问题");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
